using FluentSilverlight.Commands;
using FluentSilverlight.Expressions;
using FluentSilverlight.MVVM;

namespace FluentSilverlight.Client.Screens.XamlSample
{
    public class SampleViewModel : ViewModelBase<SampleViewModel, IOpinionatedControl<SampleViewModel>>
    {
        private bool isDirty;

        public DelegateCommand<string> UserNameChangedCommand;
        public DelegateCommand<object> SaveCommand;
        public DelegateCommand<object> CancelCommand;
        public DelegateCommand<object> VisibilityTestCommand;
        public DelegateCommand<object> VisibilityTest2Command;

        public SampleViewModel(IOpinionatedControl<SampleViewModel> view)
        {
            View = view;
            view.SetModel(this);

            UserNameChangedCommand = new DelegateCommand<string>(OnUserNameChanged);
            SaveCommand = new DelegateCommand<object>(OnSave, CanSave);
            CancelCommand = new DelegateCommand<object>(OnCancel);
            VisibilityTestCommand=new DelegateCommand<object>(OnVisibilityTest, CanExecuteVisibilityTest);
            VisibilityTest2Command=new DelegateCommand<object>(OnVisibilityTest2, CanExecuteVisibilityTest2);

            UserName = "";
            UserNameIsVisible = true;
            UserNameIsReadOnly = false;

            SaveCommandIsVisible = true;

            Status = "OK";

            WhenPropertyChanged(m => m.IsDirty).Do(() => SaveCommand.RaiseCanExecuteChanged());

            view.Initialize();
        }

        public override void Initialize()
        {
        }

        public override void InitializeData()
        {
        }

        private void OnVisibilityTest(object obj)
        {
            Status = "visibility test 1 clicked...";
        }

        private bool CanExecuteVisibilityTest()
        {
            return visibilityTestIsInteractable;
        }

        private void OnVisibilityTest2(object obj)
        {
            Status = "visibility test 2 clicked...";
        }

        private bool CanExecuteVisibilityTest2()
        {
            return visibilityTest2IsInteractable;
        }

        private void OnUserNameChanged(string newValue)
        {
            EchoedUserName = newValue;
        }

        private void OnCancel(object obj)
        {
            Status = "Cancel clicked";
            IsDirty = false;
        }

        private void OnSave(object obj)
        {
            Status = "Save clicked";
            IsDirty = false;
        }

        private bool CanSave()
        {
            return isDirty;
        }

        private bool visibilityTestIsInteractable;
        public bool VisibilityTestIsInteractable
        {
            get { return visibilityTestIsInteractable; }
            set
            {
                visibilityTestIsInteractable = value;
                OnPropertyChanged(m => m.VisibilityTestIsInteractable);
                VisibilityTestCommand.RaiseCanExecuteChanged();
            }
        }

        private bool visibilityTestIsVisible;
        public bool VisibilityTestIsVisible
        {
            get { return visibilityTestIsVisible; }
            set
            {
                visibilityTestIsVisible = value;
                OnPropertyChanged(m => m.VisibilityTestIsVisible);
            }
        }

        private bool visibilityTest2IsInteractable;
        public bool VisibilityTest2IsInteractable
        {
            get { return visibilityTest2IsInteractable; }
            set
            {
                visibilityTest2IsInteractable = value;
                OnPropertyChanged(m => m.VisibilityTest2IsInteractable);
                VisibilityTest2Command.RaiseCanExecuteChanged();
            }
        }

        private bool visibilityTest2IsVisible;
        public bool VisibilityTest2IsVisible
        {
            get { return visibilityTest2IsVisible; }
            set
            {
                visibilityTest2IsVisible = value;
                OnPropertyChanged(m => m.VisibilityTest2IsVisible);
            }
        }

        private string status;
        public string Status
        {
            get { return status; }
            set
            {
                status = value;
                OnPropertyChanged(m => m.Status);
            }
        }

        private string echoedUserName;
        public string EchoedUserName
        {
            get { return echoedUserName; }
            set
            {
                echoedUserName = value;
                OnPropertyChanged(m => m.EchoedUserName);
            }
        }

        private bool userNameIsVisible;
        public bool UserNameIsVisible
        {
            get { return userNameIsVisible; }
            set
            {
                userNameIsVisible = value;
                OnPropertyChanged(m => m.UserNameIsVisible);
            }
        }

        private bool userNameIsEnabled;
        public bool UserNameIsEnabled
        {
            get { return userNameIsEnabled; }
            set
            {
                userNameIsEnabled = value;
                OnPropertyChanged(m => m.UserNameIsEnabled);
            }
        }

        private bool userNameIsReadOnly;
        public bool UserNameIsReadOnly
        {
            get { return userNameIsReadOnly; }
            set
            {
                userNameIsReadOnly = value;
                OnPropertyChanged(m => m.UserNameIsReadOnly);
            }
        }

        private string userName;
        public string UserName
        {
            get { return userName; }
            set
            {
                userName = value;
                OnPropertyChanged(m => m.UserName);
            }
        }

        private bool saveCommandIsVisible;
        public bool SaveCommandIsVisible
        {
            get { return saveCommandIsVisible; }
            set
            {
                saveCommandIsVisible = value;
                OnPropertyChanged(m => m.SaveCommandIsVisible);
            }
        }

        public override void OnPropertyChanged(string propertyName)
        {
            base.OnPropertyChanged(propertyName);
            IsDirty = true;
        }

        public bool IsDirty
        {
            get { return isDirty; }
            private set
            {
                if (isDirty == value) return;
                isDirty = value;
                OnPropertyChanged(m => m.IsDirty);
            }
        }
    }
}